#include"Camera.h"

namespace hnurm
{
    void HKcam::Hkcam()
    {
        nRet=MV_OK;
        handle=NULL;
        pData=NULL;
        connected_flag=false;
    }

    void HKcam::SetParam()
    {
        // set width
        // 设置宽度
        // 宽设置时需考虑步进(16)，即设置宽需16的倍数
        // Step (16) should be considered when setting width, that is the width should be a multiple of 16
        unsigned int nWidthValue = 640;
        nRet = MV_CC_SetIntValue(handle, "Width", nWidthValue);
        if (MV_OK == nRet)
        {
            printf("set Width OK!\n");
        }
        else
        {
            printf("set Width failed! nRet [%x]\n", nRet);
        }

        // set height
        // 设置高度
        // 高设置时需考虑步进(2)，即设置高需16的倍数
        // Step (2) should be considered when setting height, that is the height should be a multiple of 2
        unsigned int nHeightValue = 480;
        nRet = MV_CC_SetIntValue(handle, "Height", nHeightValue);
        if (MV_OK == nRet)
        {
            printf("set height OK!\n");
        }
        else
        {
            printf("set height failed! nRet [%x]\n", nRet);
        }

        // set OffsetX
        // 设置水平偏移
        unsigned int nOffsetXValue = 0;
        nRet = MV_CC_SetIntValue(handle, "OffsetX", nOffsetXValue);
        if (MV_OK == nRet)
        {
            printf("set OffsetX OK!\n");
        }
        else
        {
            printf("set OffsetX failed! nRet [%x]\n", nRet);
        }

        // set OffsetY
        // 设置垂直偏移
        unsigned int nOffsetYValue = 0;
        nRet = MV_CC_SetIntValue(handle, "OffsetY", nOffsetYValue);
        if (MV_OK == nRet)
        {
            printf("set OffsetY OK!\n");
        }
        else
        {
            printf("set OffsetY failed! nRet [%x]\n", nRet);
        }

        // set ReverseY
        // 设置垂直镜像
        int nSetBoolValue1=0;
        bool bSetBoolValue1;
        if (0 != nSetBoolValue1)
        {
            bSetBoolValue1 = true;
        }
        else
        {
            bSetBoolValue1 = false;
        }
        nRet = MV_CC_SetBoolValue(handle, "ReverseY", bSetBoolValue1);
        if (MV_OK == nRet)
        {
            printf("Set ReverseY OK!\n");
        }
        else
        {
            printf("Set ReverseY Failed! nRet = [%x]\n", nRet);
        }

        // set PixelFormat
        // 设置像素格式
        unsigned int nPixelFormat =0x02180014;
        nRet = MV_CC_SetEnumValue(handle, "PixelFormat", nPixelFormat);
        if (MV_OK == nRet)
        {
            printf("set PixelFormat OK!\n");
        }
        else
        {
            printf("set PixelFormat failed! nRet [%x]\n", nRet);
        }

        // set BinningHorizontal
        // 设置水平合并
        unsigned int nBinningHorizontal = 1;
        nRet = MV_CC_SetEnumValue(handle, "BinningHorizontal", nBinningHorizontal);
        if (MV_OK == nRet)
        {
            printf("set BinningHorizontal OK!\n");
        }
        else
        {
            printf("set BinningHorizontal failed! nRet [%x]\n", nRet);
        }

        // set BinningVertical
        // 设置垂直合并
        unsigned int nBinningVertical = 1;
        nRet = MV_CC_SetEnumValue(handle, "BinningVertical", nBinningVertical);
        if (MV_OK == nRet)
        {
            printf("set BinningVertical OK!\n");
        }
        else
        {
            printf("set BinningVertical failed! nRet [%x]\n", nRet);
        }

        // set DecimationHorizontal
        // 设置水平下采样
        unsigned int nDecimationHorizontal = 1;
        nRet = MV_CC_SetEnumValue(handle, "DecimationHorizontal", nDecimationHorizontal);
        if (MV_OK == nRet)
        {
            printf("set DecimationHorizontal OK!\n");
        }
        else
        {
            printf("set DecimationHorizontal failed! nRet [%x]\n", nRet);
        }

        // set DecimationVertical
        // 设置垂直下采样
        unsigned int nDecimationVertical = 1;
        nRet = MV_CC_SetEnumValue(handle, "DecimationVertical", nDecimationVertical);
        if (MV_OK == nRet)
        {
            printf("set DecimationVertical OK!\n");
        }
        else
        {
            printf("set DecimationVertical failed! nRet [%x]\n", nRet);
        }

        // set AcquisitionBurstFrameCount
        // 设置采集初发帧率
        unsigned int nAcquisitionBurstFrameCountValue = 1;
        nRet = MV_CC_SetIntValue(handle, "AcquisitionBurstFrameCount",
                                 nAcquisitionBurstFrameCountValue);
        if (MV_OK == nRet)
        {
            printf("set AcquisitionBurstFrameCount OK!\n");
        }
        else
        {
            printf("set AcquisitionBurstFrameCount failed! nRet [%x]\n", nRet);
        }

        // set AcquisitionFrameRate
        // 设置采集帧率
        float fFPSValue =404.0000;
        nRet = MV_CC_SetFloatValue(handle, "AcquisitionFrameRate", fFPSValue);

        if (MV_OK == nRet)
        {
            printf("set AcquisitionFrameRate OK!\n");
        }
        else
        {
            printf("set AcquisitionFrameRate failed! nRet [%x]\n", nRet);
        }

        // set AcquisitionFrameRateEnable
        // 设置使能采集帧率控制
        int nSetBoolValue3=1;
        bool bSetBoolValue3;
        if (0 != nSetBoolValue3)
        {
            bSetBoolValue3 = true;
        }
        else
        {
            bSetBoolValue3 = false;
        }
        nRet = MV_CC_SetBoolValue(handle, "AcquisitionFrameRateEnable", bSetBoolValue3);
        if (MV_OK == nRet)
        {
            printf("Set AcquisitionFrameRateEnable OK!\n");
        }
        else
        {
            printf("Set AcquisitionFrameRateEnable Failed! nRet = [%x]\n", nRet);
        }

        // set ExposureTime
        // 设置曝光时间
        float fExposureTime =7000.0000;
        nRet = MV_CC_SetFloatValue(handle, "ExposureTime", fExposureTime);
        if (MV_OK == nRet)
        {
            printf("set ExposureTime OK!\n");
        }
        else
        {
            printf("set ExposureTime failed! nRet [%x]\n", nRet);
        }

        // set Gain
        // 设置增益
        float fGainvalue = 15.0062;
        nRet = MV_CC_SetFloatValue(handle, "Gain", fGainvalue);
        if (MV_OK == nRet)
        {
            printf("set Gain OK!\n");
        }
        else
        {
            printf("set Gain failed! nRet [%x]\n", nRet);
        }

        // set GainAuto
        // 设置自动增益
        unsigned int nGainAuto = 0;
        nRet = MV_CC_SetEnumValue(handle, "GainAuto", nGainAuto);
        if (MV_OK == nRet)
        {
            printf("set GainAuto OK!\n");
        }
        else
        {
            printf("set GainAuto failed! nRet [%x]\n", nRet);
        }

        // set Blacklevel
        // 设置黑电平
        unsigned int nBlacklevelvalue = 30;
        nRet = MV_CC_SetIntValue(handle, "BlackLevel", nBlacklevelvalue);
        if (MV_OK == nRet)
        {
            printf("set Blacklevel OK!\n");
        }
        else
        {
            printf("set Blacklevel failed! nRet [%x]\n", nRet);
        }

        // set BlackLevelEnable
        // 设置黑电平使能
        int nSetBoolValue2=1;
        bool bSetBoolValue2;
        if (0 != nSetBoolValue2)
        {
            bSetBoolValue2 = true;
        }
        else
        {
            bSetBoolValue2 = false;
        }
        nRet = MV_CC_SetBoolValue(handle, "BlackLevelEnable", bSetBoolValue2);
        if (MV_OK == nRet)
        {
            printf("Set BlackLevelEnable OK!\n");
        }
        else
        {
            printf("Set BlackLevelEnable Failed! nRet = [%x]\n", nRet);
        }
        // set Gamma
        // 设置伽马校正
        float fGammaValue =0.7400;
        nRet = MV_CC_SetFloatValue(handle, "Gamma", fGammaValue);
        if (MV_OK == nRet)
        {
            printf("set Gamma OK!\n");
        }
        else
        {
            printf("set Gamma failed! nRet [%x]\n", nRet);
        }

        // set GammaEnable
        // 设置伽马校正使能
        int nSetBoolValue4=1;
        bool bSetBoolValue4;
        if (0 != nSetBoolValue4)
        {
            bSetBoolValue4 = true;
        }
        else
        {
            bSetBoolValue4 = false;
        }
        nRet = MV_CC_SetBoolValue(handle, "GammaEnable", bSetBoolValue4);
        if (MV_OK == nRet)
        {
            printf("Set GammaEnable OK!\n");
        }
        else
        {
            printf("Set GammaEnable Failed! nRet = [%x]\n", nRet);
        }
    }

    bool HKcam::OpenCam()
    {
        nRet = MV_OK;

        MV_CC_DEVICE_INFO_LIST stDeviceList;
        memset(&stDeviceList, 0, sizeof(MV_CC_DEVICE_INFO_LIST));
        // 枚举设备
        // enum device
        nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &stDeviceList);
        if (!stDeviceList.nDeviceNum)
        {
            printf("Find No Devices!\n");
            return false;
        }

        //select the first camera connected
        unsigned int nIndex = 0;

        // 选择设备并创建句柄
        // select device and create handle
        nRet = MV_CC_CreateHandle(&handle, stDeviceList.pDeviceInfo[nIndex]);
        if (MV_OK != nRet)
        {
            printf("MV_CC_CreateHandle fail! nRet [%x]\n", nRet);
            return false;
        }

        // 打开设备
        // open device
        nRet = MV_CC_OpenDevice(handle);
        if (MV_OK != nRet)
        {
            printf("MV_CC_OpenDevice fail! nRet [%x]\n", nRet);
            return false;
        }

        // 设置触发模式为off
        // set trigger mode as off
        nRet = MV_CC_SetEnumValue(handle, "TriggerMode", 0);
        if (MV_OK != nRet)
        {
            printf("MV_CC_SetTriggerMode fail! nRet [%x]\n", nRet);
            return false;
        }

        // set param
        // 设置参数
        SetParam();

        // Get payload size
        memset(&stParam, 0, sizeof(MVCC_INTVALUE));
        nRet = MV_CC_GetIntValue(handle, "PayloadSize", &stParam);
        if (MV_OK != nRet)
        {
            printf("Get PayloadSize fail! nRet [0x%x]\n", nRet);
            return false;
        }

        //s tart grab stream
        nRet = MV_CC_StartGrabbing(handle);
        if (MV_OK != nRet)
        {
            printf("Start Grabbing fail! nRet [0x%x]\n", nRet);
            return false;
        }

        // check
        stImageInfo = {0};
        memset(&stImageInfo, 0, sizeof(MV_FRAME_OUT_INFO_EX));
        pData = (unsigned char *)malloc(sizeof(unsigned char) * stParam.nCurValue);
        if (NULL == pData)
        {
            std::cout<<"can't get size of a frame!"<<std::endl;
            return false;
        }

        connected_flag=true;

        return true;
    }


    bool HKcam::CloseCam()
    {
        // 停止取流
        // end grab image
        nRet = MV_CC_StopGrabbing(handle);
        if (MV_OK != nRet)
        {
            printf("MV_CC_StopGrabbing fail! nRet [%x]\n", nRet);
            return false;
        }
        // 关闭设备
        // close device
        nRet = MV_CC_CloseDevice(handle);
        if (MV_OK != nRet)
        {
            printf("MV_CC_CloseDevice fail! nRet [%x]\n", nRet);
            return false;
        }
        // 销毁句柄
        // destroy handle
        nRet = MV_CC_DestroyHandle(handle);
        if (MV_OK != nRet)
        {
            printf("MV_CC_DestroyHandle fail! nRet [%x]\n", nRet);
            return false;
        }
        return true;
    }


    bool HKcam::GetFlame(ImgInfo& img)
    {
        nRet = MV_OK;
        nRet = MV_CC_GetOneFrameTimeout(handle, pData, stParam.nCurValue, &stImageInfo, 100);

        if (nRet != MV_OK)
        {
            printf("No data[0x%x]\n", nRet);
            return false;
        }

        //if you want change the format ,edit here

        img.frame=cv::Mat(stImageInfo.nHeight,stImageInfo.nWidth,CV_8UC3,pData);
        return true;
    }

} // namespace hnurm
